package com.dt.platform.oa.controller;

import java.util.*;
import com.dt.platform.domain.oa.CrmCustomer;
import com.dt.platform.domain.oa.ProjectPhase;
import com.dt.platform.domain.oa.meta.ProjectPhaseMeta;
import com.github.foxnic.commons.lang.StringUtil;
import com.github.foxnic.dao.data.Rcd;
import com.github.foxnic.dao.data.RcdSet;
import com.github.foxnic.sql.expr.ConditionExpr;
import org.github.foxnic.web.domain.hrm.Person;
import org.github.foxnic.web.framework.web.SuperController;
import org.github.foxnic.web.session.SessionUser;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import com.github.foxnic.commons.collection.CollectorUtil;
import com.github.foxnic.dao.entity.ReferCause;
import com.github.foxnic.api.swagger.InDoc;
import org.github.foxnic.web.framework.sentinel.SentinelExceptionUtil;
import com.github.foxnic.api.swagger.ApiParamSupport;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.dt.platform.proxy.oa.ProjectServiceProxy;
import com.dt.platform.domain.oa.meta.ProjectVOMeta;
import com.dt.platform.domain.oa.Project;
import com.dt.platform.domain.oa.ProjectVO;
import com.github.foxnic.api.transter.Result;
import com.github.foxnic.dao.data.SaveMode;
import com.github.foxnic.dao.excel.ExcelWriter;
import com.github.foxnic.springboot.web.DownloadUtil;
import com.github.foxnic.dao.data.PagedList;
import java.util.Date;
import java.sql.Timestamp;
import com.github.foxnic.api.error.ErrorDesc;
import com.github.foxnic.commons.io.StreamUtil;
import java.util.Map;
import com.github.foxnic.dao.excel.ValidateResult;
import java.io.InputStream;
import java.util.stream.Collectors;

import com.dt.platform.domain.oa.meta.ProjectMeta;
import org.github.foxnic.web.domain.hrm.Employee;
import org.github.foxnic.web.domain.system.DictItem;
import com.foxnicweb.web.domain.contract.Contract;
import org.github.foxnic.web.domain.hrm.Organization;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiImplicitParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.dt.platform.oa.service.IProjectService;
import com.github.foxnic.api.validate.annotations.NotNull;

/**
 * <p>
 * 项目管理接口控制器
 * </p>
 * @author 金杰 , maillank@qq.com
 * @since 2025-06-19 21:01:03
 */
@InDoc
@Api(tags = "项目管理")
@RestController("OaProjectController")
public class ProjectController extends SuperController {

    @Autowired
    private IProjectService projectService;

    /**
     * 添加项目管理
     */
    @ApiOperation(value = "添加项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.CODE, value = "项目编号", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CONTRACT_ID, value = "关联合同", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CUR_PHASE, value = "当前阶段", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.LEADER_ID, value = "项目经理", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.NAME, value = "项目名称", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.ORG_ID, value = "归属部门", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.OWNER_ID, value = "创建人员", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROFILE, value = "项目介绍", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROJECT_STATUS, value = "项目状态", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.TYPE, value = "项目类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.FILE_ID, value = "附件", required = false, dataTypeClass = String.class)
	})
    @ApiParamSupport(ignoreDBTreatyProperties = true, ignoreDefaultVoProperties = true, ignorePrimaryKey = true)
    @ApiOperationSupport(order = 1, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.INSERT, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.INSERT)
    public Result insert(ProjectVO projectVO) {
        Result result = projectService.insert(projectVO, false);
        return result;
    }

    /**
     */
    @ApiOperation(value = "动作")
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.ACTION, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.ACTION)
    public Result action(String id, String action,String ct) {
        Result result = projectService.action(id, action,ct);
        return result;
    }

    /**
     * 删除项目管理
     */
    @ApiOperation(value = "删除项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class)
	})
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.DELETE, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.DELETE)
    public Result deleteById(String id) {
        this.validator().asserts(id).require("缺少id值");
        if (this.validator().failure()) {
            return this.validator().getFirstResult();
        }
        // 引用校验
        ReferCause cause = projectService.hasRefers(id);
        // 判断是否可以删除
        this.validator().asserts(cause.hasRefer()).requireEqual("不允许删除当前记录：" + cause.message(), false);
        if (this.validator().failure()) {
            return this.validator().getFirstResult().messageLevel4Confirm();
        }
        Result result = projectService.deleteByIdLogical(id);
        return result;
    }

    /**
     * 批量删除项目管理 <br>
     * 联合主键时，请自行调整实现
     */
    @ApiOperation(value = "批量删除项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.IDS, value = "主键清单", required = true, dataTypeClass = List.class, example = "[1,3,4]")
	})
    @ApiOperationSupport(order = 3, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.DELETE_BY_IDS, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.DELETE_BY_IDS)
    public Result deleteByIds(List<String> ids) {
        // 参数校验
        this.validator().asserts(ids).require("缺少ids参数");
        if (this.validator().failure()) {
            return this.validator().getFirstResult();
        }
        // 查询引用
        Map<String, ReferCause> causeMap = projectService.hasRefers(ids);
        // 收集可以删除的ID值
        List<String> canDeleteIds = new ArrayList<>();
        for (Map.Entry<String, ReferCause> e : causeMap.entrySet()) {
            if (!e.getValue().hasRefer()) {
                canDeleteIds.add(e.getKey());
            }
        }
        // 执行删除
        if (canDeleteIds.isEmpty()) {
            // 如果没有一行可以被删除
            return ErrorDesc.failure().message("无法删除您选中的数据行：").data(0).addErrors(CollectorUtil.collectArray(CollectorUtil.filter(causeMap.values(), (e) -> {
                return e.hasRefer();
            }), ReferCause::message, String.class)).messageLevel4Confirm();
        } else if (canDeleteIds.size() == ids.size()) {
            // 如果全部可以删除
            Result result = projectService.deleteByIdsLogical(canDeleteIds);
            return result;
        } else if (canDeleteIds.size() > 0 && canDeleteIds.size() < ids.size()) {
            // 如果部分行可以删除
            Result result = projectService.deleteByIdsLogical(canDeleteIds);
            if (result.failure()) {
                return result;
            } else {
                return ErrorDesc.success().message("已删除 " + canDeleteIds.size() + " 行，但另有 " + (ids.size() - canDeleteIds.size()) + " 行数据无法删除").data(canDeleteIds.size()).addErrors(CollectorUtil.collectArray(CollectorUtil.filter(causeMap.values(), (e) -> {
                    return e.hasRefer();
                }), ReferCause::message, String.class)).messageLevel4Confirm();
            }
        } else {
            // 理论上，这个分支不存在
            return ErrorDesc.success().message("数据删除未处理");
        }
    }

    /**
     * 更新项目管理
     */
    @ApiOperation(value = "更新项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.CODE, value = "项目编号", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CONTRACT_ID, value = "关联合同", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CUR_PHASE, value = "当前阶段", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.LEADER_ID, value = "项目经理", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.NAME, value = "项目名称", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.ORG_ID, value = "归属部门", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.OWNER_ID, value = "创建人员", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROFILE, value = "项目介绍", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROJECT_STATUS, value = "项目状态", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.TYPE, value = "项目类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.FILE_ID, value = "附件", required = false, dataTypeClass = String.class)
	})
    @ApiParamSupport(ignoreDBTreatyProperties = true, ignoreDefaultVoProperties = true)
    @ApiOperationSupport(order = 4, author = "金杰 , maillank@qq.com", ignoreParameters = { ProjectVOMeta.PAGE_INDEX, ProjectVOMeta.PAGE_SIZE, ProjectVOMeta.SEARCH_FIELD, ProjectVOMeta.FUZZY_FIELD, ProjectVOMeta.SEARCH_VALUE, ProjectVOMeta.DIRTY_FIELDS, ProjectVOMeta.SORT_FIELD, ProjectVOMeta.SORT_TYPE, ProjectVOMeta.DATA_ORIGIN, ProjectVOMeta.QUERY_LOGIC, ProjectVOMeta.REQUEST_ACTION, ProjectVOMeta.IDS })
    @SentinelResource(value = ProjectServiceProxy.UPDATE, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.UPDATE)
    public Result update(ProjectVO projectVO) {
        Result result = projectService.update(projectVO, SaveMode.DIRTY_OR_NOT_NULL_FIELDS, false);
        return result;
    }

    /**
     * 保存项目管理
     */
    @ApiOperation(value = "保存项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.CODE, value = "项目编号", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CONTRACT_ID, value = "关联合同", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CUR_PHASE, value = "当前阶段", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.LEADER_ID, value = "项目经理", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.NAME, value = "项目名称", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.ORG_ID, value = "归属部门", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.OWNER_ID, value = "创建人员", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROFILE, value = "项目介绍", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROJECT_STATUS, value = "项目状态", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.TYPE, value = "项目类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.FILE_ID, value = "附件", required = false, dataTypeClass = String.class)
	})
    @ApiParamSupport(ignoreDBTreatyProperties = true, ignoreDefaultVoProperties = true)
    @ApiOperationSupport(order = 5, ignoreParameters = { ProjectVOMeta.PAGE_INDEX, ProjectVOMeta.PAGE_SIZE, ProjectVOMeta.SEARCH_FIELD, ProjectVOMeta.FUZZY_FIELD, ProjectVOMeta.SEARCH_VALUE, ProjectVOMeta.DIRTY_FIELDS, ProjectVOMeta.SORT_FIELD, ProjectVOMeta.SORT_TYPE, ProjectVOMeta.DATA_ORIGIN, ProjectVOMeta.QUERY_LOGIC, ProjectVOMeta.REQUEST_ACTION, ProjectVOMeta.IDS })
    @SentinelResource(value = ProjectServiceProxy.SAVE, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.SAVE)
    public Result save(ProjectVO projectVO) {
        Result result = projectService.save(projectVO, SaveMode.DIRTY_OR_NOT_NULL_FIELDS, false);
        return result;
    }

    /**
     * 获取项目管理
     */
    @ApiOperation(value = "获取项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "1")
	})
    @ApiOperationSupport(order = 6, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.GET_BY_ID, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.GET_BY_ID)
    public Result<Project> getById(String id) {
        Result<Project> result = new Result<>();
        Project project = projectService.getById(id);
        // join 关联的对象
        projectService.dao().fill(project).with(ProjectMeta.PROJECT_PHASE_LIST).with(ProjectMeta.PART_USER_LIST).with(ProjectMeta.PROJECT_PHASE).with(ProjectMeta.LEADER).with(ProjectMeta.ORGANIZATION).with(ProjectMeta.OWNER).with(ProjectMeta.WORK_TYPE_DICT).with(ProjectMeta.CONTRACT).execute();


        projectService.dao().join(project.getLeader(), Person.class);
        projectService.dao().join(project.getOwner(), Person.class);

        if(project.getProjectPhaseList()!=null&&project.getProjectPhaseList().size()>0){
            projectService.dao().fill(project.getProjectPhaseList()).with(ProjectPhaseMeta.LEADER).execute();
            List<Employee> phaseLeaders = CollectorUtil.collectList(project.getProjectPhaseList(), ProjectPhase::getLeader);
            projectService.dao().join(phaseLeaders, Person.class);
        }

        ProjectPhase phase=project.getProjectPhase();
        if(phase!=null){
            projectService.dao().fill(phase).with(ProjectPhaseMeta.LEADER).execute();
            projectService.dao().join(phase.getLeader(), Person.class);
        }

        String sql = "select \n" + "project_id id,\n" + "sum(case task_status when 'acting' then cnt else 0 end) acting_cnt,\n" + "sum(case task_status when 'wait' then cnt else 0 end)   wait_cnt,\n" + "sum(case task_status when 'finish' then cnt else 0 end) finish_cnt,\n" + "sum(case task_status when 'close' then cnt else 0 end) close_cnt,\n" + "sum(case task_status when 'cancel' then cnt else 0 end) cancel_cnt\n" + "from (\n" + "select project_id, task_status,count(1) cnt \n" + "from oa_project_task \n" + "where project_id=? and project_id is not null and deleted=0\n" + "group by project_id, task_status  \n" + ") tab where 1=1 group by project_id ";
        RcdSet rs = projectService.dao().query(sql, id);
        Map<Object, Rcd> map = rs.getMappedRcds("id");
        if (map.containsKey(id)) {
            Rcd rcd = map.get(id);
            int total = rcd.getInteger("acting_cnt") + rcd.getInteger("wait_cnt") + rcd.getInteger("finish_cnt");
            int acting = rcd.getInteger("acting_cnt") + rcd.getInteger("wait_cnt");
            project.setTaskCompleteCount(rcd.getInteger("finish_cnt") + "");
            project.setTaskCount(total + "");
            project.setTaskActingCount(acting + "");
            if (total == 0) {
                project.setTaskCompletePct("0");
            } else {
                project.setTaskCompletePct((rcd.getInteger("finish_cnt") / total) + "");
            }
        } else {
            project.setTaskCompleteCount("0");
            project.setTaskCount("0");
            project.setTaskActingCount("0");
            project.setTaskCompletePct("0");
        }
        String sql2 = "select b.project_id id,sum(estimate_w_time) plan_work_time,sum(work_time) work_time,count(1) work_count \n" + "from oa_project_task_rcd a,oa_project_task b \n" + "where a.task_id=b.id and a.deleted=0 and b.deleted=0 \n" + "and b.task_status in ('wait','acting','finish')\n" + "and b.project_id=?\n" + "group by b.project_id";
        RcdSet rs2 = projectService.dao().query(sql2, id);
        Map<Object, Rcd> map2 = rs2.getMappedRcds("id");
        if (map2.containsKey(id)) {
            Rcd rcd2 = map2.get(id);
            project.setWorkTimeTotal(rcd2.getString("work_time"));
            project.setTaskRcdCount(rcd2.getString("work_count"));
            project.setPlanWorkTimeTotal(rcd2.getString("plan_work_time"));
        } else {
            project.setWorkTimeTotal("0");
            project.setTaskRcdCount("0");
            project.setPlanWorkTimeTotal("0");
        }


        result.success(true).data(project);
        return result;
    }

    /**
     * 批量获取项目管理 <br>
     * 联合主键时，请自行调整实现
     */
    @ApiOperation(value = "批量获取项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.IDS, value = "主键清单", required = true, dataTypeClass = List.class, example = "[1,3,4]")
	})
    @ApiOperationSupport(order = 3, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.GET_BY_IDS, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.GET_BY_IDS)
    public Result<List<Project>> getByIds(List<String> ids) {
        Result<List<Project>> result = new Result<>();
        List<Project> list = projectService.queryListByIds(ids);
        result.success(true).data(list);
        return result;
    }

    /**
     * 查询项目管理
     */
    @ApiOperation(value = "查询项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.CODE, value = "项目编号", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CONTRACT_ID, value = "关联合同", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CUR_PHASE, value = "当前阶段", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.LEADER_ID, value = "项目经理", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.NAME, value = "项目名称", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.ORG_ID, value = "归属部门", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.OWNER_ID, value = "创建人员", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROFILE, value = "项目介绍", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROJECT_STATUS, value = "项目状态", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.TYPE, value = "项目类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.FILE_ID, value = "附件", required = false, dataTypeClass = String.class)
	})
    @ApiOperationSupport(order = 5, author = "金杰 , maillank@qq.com", ignoreParameters = { ProjectVOMeta.PAGE_INDEX, ProjectVOMeta.PAGE_SIZE })
    @SentinelResource(value = ProjectServiceProxy.QUERY_LIST, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.QUERY_LIST)
    public Result<List<Project>> queryList(ProjectVO sample) {
        Result<List<Project>> result = new Result<>();
        List<Project> list = projectService.queryList(sample);
        result.success(true).data(list);
        return result;
    }

    /**
     * 分页查询项目管理
     */
    @ApiOperation(value = "分页查询项目管理")
    @ApiImplicitParams({
		@ApiImplicitParam(name = ProjectVOMeta.CODE, value = "项目编号", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CONTRACT_ID, value = "关联合同", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.CUR_PHASE, value = "当前阶段", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.LEADER_ID, value = "项目经理", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.NAME, value = "项目名称", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.ORG_ID, value = "归属部门", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.OWNER_ID, value = "创建人员", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROFILE, value = "项目介绍", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.PROJECT_STATUS, value = "项目状态", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class),
		@ApiImplicitParam(name = ProjectVOMeta.TYPE, value = "项目类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = ProjectVOMeta.FILE_ID, value = "附件", required = false, dataTypeClass = String.class)
	})
    @ApiOperationSupport(order = 8, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = ProjectServiceProxy.QUERY_PAGED_LIST, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(ProjectServiceProxy.QUERY_PAGED_LIST)
    public Result<PagedList<Project>> queryPagedList(ProjectVO sample) {
        Result<PagedList<Project>> result = new Result<>();
        ConditionExpr expr = new ConditionExpr();
        expr.and("1=1");
        if (!StringUtil.isBlank(sample.getSelectRange())) {
            if ("mine".equals(sample.getSelectRange())) {
                String cUserId = SessionUser.getCurrent().getActivatedEmployeeId();
                // 只有项目中有指定，就可见
                String ownerSql = "select distinct project_id from (\n" + "select 'project' range_type,leader_id user_id,'leader' join_type, id owner_source,id project_id from oa_project where deleted=0  and leader_id is not null and leader_id<>''\n" + "union all\n" + "select 'project' range_type,user_id,'member' join_type, id owner_source,project_id project_id from oa_project_user where     deleted=0 and status='in' and own_type='project' and user_id is not null and user_id<>''\n" + "union all\n" + "select 'task' range_type,leader_id,'leader' join_type,id owner_source,project_id project_id from oa_project_task where deleted=0   and leader_id is not null and leader_id<>''\n" + "union all\n" + "select 'task' range_type,b.user_id,'member' join_type,a.id owner_source,a.project_id project_id from oa_project_task a,oa_project_user b where a.id=b.project_id and a.deleted=0   and b.user_id is not null and b.user_id<>''\n" + "union all\n" + "select 'phase' range_type,leader_id,'leader' join_type,id owner_source ,project_id project_id from oa_project_phase where deleted=0   and leader_id is not null and leader_id<>''\n" + "union all\n" + "select 'phase' range_type,b.user_id,'member' join_type,a.id owner_source,a.project_id project_id from oa_project_phase a,oa_project_user b where a.id=b.project_id and a.deleted=0   and b.user_id is not null and b.user_id<>''\n" + ") tab where user_id=? and project_id is not null and project_id<>''";
                expr.and("id in (" + ownerSql + ")", cUserId);
            }
        }
        if (!StringUtil.isBlank(sample.getTabStatus())) {
            if("acting".equals(sample.getTabStatus())){
                expr.and("project_status in ('wait','acting')");
            }else if("finish".equals(sample.getTabStatus())){
                expr.and("project_status in ('finish','close','cancel')");
            }
        }

        PagedList<Project> list = projectService.queryPagedList(sample, expr, sample.getPageSize(), sample.getPageIndex());
        // join 关联的对象
        projectService.dao().fill(list).with(ProjectMeta.LEADER).with(ProjectMeta.OWNER).with(ProjectMeta.PROJECT_PHASE).with(ProjectMeta.WORK_TYPE_DICT).with(ProjectMeta.CONTRACT).execute();
        List<Employee> owners = CollectorUtil.collectList(list, Project::getOwner);
        List<Employee> leaders = CollectorUtil.collectList(list, Project::getLeader);


        projectService.dao().join(owners, Person.class);
        projectService.dao().join(leaders, Person.class);


        List<ProjectPhase> phaseList2 = CollectorUtil.collectList(list, Project::getProjectPhase);
        List<ProjectPhase> phaseList=phaseList2.stream().filter(item->item!=null).collect(Collectors.toList());

        if(phaseList!=null){
            projectService.dao().fill(phaseList).with(ProjectPhaseMeta.LEADER).execute();
            List<Employee> phaseLeaderList = CollectorUtil.collectList(phaseList, ProjectPhase::getLeader);
            projectService.dao().join(phaseLeaderList, Person.class);
        }


        String sql = "select \n" + "project_id id,\n" + "sum(case task_status when 'acting' then cnt else 0 end) acting_cnt,\n" + "sum(case task_status when 'wait' then cnt else 0 end)   wait_cnt,\n" + "sum(case task_status when 'finish' then cnt else 0 end) finish_cnt,\n" + "sum(case task_status when 'close' then cnt else 0 end) close_cnt,\n" + "sum(case task_status when 'cancel' then cnt else 0 end) cancel_cnt\n" + "from (\n" + "select project_id, task_status,count(1) cnt \n" + "from oa_project_task \n" + "where project_id is not null and deleted=0\n" + "group by project_id, task_status  \n" + ") tab where 1=1 group by project_id ";
        String sql2 = "select b.project_id id,sum(work_time) work_time \n" + "from oa_project_task_rcd a,oa_project_task b \n" + "where a.task_id=b.id and a.deleted=0 and b.deleted=0 \n" + "and b.task_status in ('wait','acting','finish')\n" + "group by b.project_id";

        RcdSet rs = projectService.dao().query(sql);
        RcdSet rs2 = projectService.dao().query(sql2);
        Map<Object, Rcd> map = rs.getMappedRcds("id");
        Map<Object, Rcd> map2 = rs2.getMappedRcds("id");
        for (int i = 0; i < list.getList().size(); i++) {
            String id = list.getList().get(i).getId();
            // 工时统计
            if (map2.containsKey(id)) {
                Rcd rcd2 = map2.get(id);
                list.getList().get(i).setWorkTimeTotal(rcd2.getString("work_time"));
            } else {
                list.getList().get(i).setWorkTimeTotal("0");
            }
            // 任务统计
            if (map.containsKey(id)) {
                Rcd rcd = map.get(id);
                int total = rcd.getInteger("acting_cnt") + rcd.getInteger("wait_cnt") + rcd.getInteger("finish_cnt");
                int acting = rcd.getInteger("acting_cnt") + rcd.getInteger("wait_cnt");
                list.getList().get(i).setTaskCompleteCount(rcd.getInteger("finish_cnt") + "");
                list.getList().get(i).setTaskCount(total + "");
                list.getList().get(i).setTaskActingCount(acting + "");
                if (total == 0) {
                    list.getList().get(i).setTaskCompletePct("0");
                } else {
                    list.getList().get(i).setTaskCompletePct(  ((rcd.getInteger("finish_cnt") / total))*100 + "");
                }
            } else {
                list.getList().get(i).setTaskCompleteCount("0");
                list.getList().get(i).setTaskCount("0");
                list.getList().get(i).setTaskActingCount("0");
                list.getList().get(i).setTaskCompletePct("0");
            }
        }
        result.success(true).data(list);
        return result;
    }
}
